namespace SumerCoreDevOps.Infrastructure.Distributed;

/// <summary>
/// 分布式协调器接口，用于多主节点间的状态共享和协调
/// </summary>
public interface IDistributedCoordinator
{
    /// <summary>
    /// 获取分布式锁
    /// </summary>
    /// <param name="key">锁的键</param>
    /// <param name="timeout">锁的超时时间</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>分布式锁对象，使用完毕后需要释放</returns>
    Task<IDistributedLock?> AcquireLockAsync(string key, TimeSpan timeout, CancellationToken cancellationToken = default);

    /// <summary>
    /// 尝试获取分布式锁（非阻塞）
    /// </summary>
    /// <param name="key">锁的键</param>
    /// <param name="timeout">锁的超时时间</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>如果获取成功返回锁对象，否则返回null</returns>
    Task<IDistributedLock?> TryAcquireLockAsync(string key, TimeSpan timeout, CancellationToken cancellationToken = default);

    /// <summary>
    /// 设置共享数据
    /// </summary>
    /// <typeparam name="T">数据类型</typeparam>
    /// <param name="key">键</param>
    /// <param name="value">值</param>
    /// <param name="expiry">过期时间，null表示永不过期</param>
    /// <param name="cancellationToken">取消令牌</param>
    Task SetAsync<T>(string key, T value, TimeSpan? expiry = null, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取共享数据
    /// </summary>
    /// <typeparam name="T">数据类型</typeparam>
    /// <param name="key">键</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>值，如果不存在返回default(T)</returns>
    Task<T?> GetAsync<T>(string key, CancellationToken cancellationToken = default);

    /// <summary>
    /// 删除共享数据
    /// </summary>
    /// <param name="key">键</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>是否删除成功</returns>
    Task<bool> DeleteAsync(string key, CancellationToken cancellationToken = default);

    /// <summary>
    /// 批量删除共享数据（支持模式匹配）
    /// </summary>
    /// <param name="pattern">键的模式，例如 "prefix:*"</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>删除的键数量</returns>
    Task<long> DeletePatternAsync(string pattern, CancellationToken cancellationToken = default);

    /// <summary>
    /// 检查键是否存在
    /// </summary>
    /// <param name="key">键</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>是否存在</returns>
    Task<bool> ExistsAsync(string key, CancellationToken cancellationToken = default);

    /// <summary>
    /// 设置键的过期时间
    /// </summary>
    /// <param name="key">键</param>
    /// <param name="expiry">过期时间</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>是否设置成功</returns>
    Task<bool> ExpireAsync(string key, TimeSpan expiry, CancellationToken cancellationToken = default);

    /// <summary>
    /// 发布消息到指定频道
    /// </summary>
    /// <typeparam name="T">消息类型</typeparam>
    /// <param name="channel">频道名称</param>
    /// <param name="message">消息内容</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>接收到消息的订阅者数量</returns>
    Task<long> PublishAsync<T>(string channel, T message, CancellationToken cancellationToken = default);

    /// <summary>
    /// 订阅指定频道
    /// </summary>
    /// <typeparam name="T">消息类型</typeparam>
    /// <param name="channel">频道名称</param>
    /// <param name="handler">消息处理器</param>
    /// <param name="cancellationToken">取消令牌</param>
    Task SubscribeAsync<T>(string channel, Func<T, Task> handler, CancellationToken cancellationToken = default);

    /// <summary>
    /// 取消订阅指定频道
    /// </summary>
    /// <param name="channel">频道名称</param>
    /// <param name="cancellationToken">取消令牌</param>
    Task UnsubscribeAsync(string channel, CancellationToken cancellationToken = default);

    /// <summary>
    /// Hash 操作：设置字段值
    /// </summary>
    /// <typeparam name="T">值类型</typeparam>
    /// <param name="key">Hash键</param>
    /// <param name="field">字段名</param>
    /// <param name="value">字段值</param>
    /// <param name="cancellationToken">取消令牌</param>
    Task HashSetAsync<T>(string key, string field, T value, CancellationToken cancellationToken = default);

    /// <summary>
    /// Hash 操作：获取字段值
    /// </summary>
    /// <typeparam name="T">值类型</typeparam>
    /// <param name="key">Hash键</param>
    /// <param name="field">字段名</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>字段值</returns>
    Task<T?> HashGetAsync<T>(string key, string field, CancellationToken cancellationToken = default);

    /// <summary>
    /// Hash 操作：获取所有字段
    /// </summary>
    /// <typeparam name="T">值类型</typeparam>
    /// <param name="key">Hash键</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>所有字段和值的字典</returns>
    Task<Dictionary<string, T>> HashGetAllAsync<T>(string key, CancellationToken cancellationToken = default);

    /// <summary>
    /// Hash 操作：删除字段
    /// </summary>
    /// <param name="key">Hash键</param>
    /// <param name="field">字段名</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>是否删除成功</returns>
    Task<bool> HashDeleteAsync(string key, string field, CancellationToken cancellationToken = default);

    /// <summary>
    /// 注册主节点
    /// </summary>
    /// <param name="masterId">主节点ID</param>
    /// <param name="host">主机地址</param>
    /// <param name="tcpPort">TCP端口</param>
    /// <param name="apiPort">API端口</param>
    /// <param name="cancellationToken">取消令牌</param>
    Task RegisterMasterAsync(string masterId, string host, int tcpPort, int apiPort, CancellationToken cancellationToken = default);

    /// <summary>
    /// 更新主节点心跳
    /// </summary>
    /// <param name="masterId">主节点ID</param>
    /// <param name="cancellationToken">取消令牌</param>
    Task UpdateMasterHeartbeatAsync(string masterId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取所有在线主节点
    /// </summary>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>主节点信息列表</returns>
    Task<List<MasterInfo>> GetOnlineMastersAsync(CancellationToken cancellationToken = default);

    /// <summary>
    /// 注销主节点
    /// </summary>
    /// <param name="masterId">主节点ID</param>
    /// <param name="cancellationToken">取消令牌</param>
    Task UnregisterMasterAsync(string masterId, CancellationToken cancellationToken = default);
}

/// <summary>
/// 分布式锁接口
/// </summary>
public interface IDistributedLock : IAsyncDisposable
{
    /// <summary>
    /// 锁的键
    /// </summary>
    string Key { get; }

    /// <summary>
    /// 锁的令牌（用于验证锁的所有权）
    /// </summary>
    string Token { get; }

    /// <summary>
    /// 是否已获取锁
    /// </summary>
    bool IsAcquired { get; }

    /// <summary>
    /// 延长锁的过期时间
    /// </summary>
    /// <param name="expiry">新的过期时间</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>是否延长成功</returns>
    Task<bool> ExtendAsync(TimeSpan expiry, CancellationToken cancellationToken = default);

    /// <summary>
    /// 释放锁
    /// </summary>
    /// <param name="cancellationToken">取消令牌</param>
    Task ReleaseAsync(CancellationToken cancellationToken = default);
}

/// <summary>
/// 主节点信息
/// </summary>
public class MasterInfo
{
    /// <summary>
    /// 主节点ID
    /// </summary>
    public string MasterId { get; set; } = string.Empty;

    /// <summary>
    /// 主机地址
    /// </summary>
    public string Host { get; set; } = string.Empty;

    /// <summary>
    /// TCP端口
    /// </summary>
    public int TcpPort { get; set; }

    /// <summary>
    /// API端口
    /// </summary>
    public int ApiPort { get; set; }

    /// <summary>
    /// 最后心跳时间
    /// </summary>
    public DateTime LastHeartbeat { get; set; }

    /// <summary>
    /// 是否在线
    /// </summary>
    public bool IsOnline { get; set; }
}
